#pragma once 

#include <string>
#include <iostream>
#include <vector>

#include "./util.hpp"
#include "./reactor.hpp"
#include "./io_service_core.hpp"

int recver(Event* p_ev)
{
    std::cout << "recver has been called" << std::endl;

    int result = recver_core(p_ev->_sock, p_ev->_inbuffer);
    if (result <= 0)
    {
        //如果这个事件设置了errorer回调函数,那么就调用它
        if (p_ev->_errorer)
        {
            p_ev->_errorer(p_ev);
        }
        return -1;
    }

    //将读取上来的数据,进行分包处理(解决粘包的问题)
    std::vector<std::string> tokens; 
    //设置|为分隔符
    std::string separator = "|";
    //将分割好的内容放入到vector中
    split_segment(p_ev->_inbuffer, tokens, separator);

    //反序列化,针对一个报文,提取有效参与计算或者存储的信息
    for (auto& seg : tokens)
    {
        std::string data1, data2, op;
        if (no_serializable(seg, data1, data2, op))
        {
            //这里就是和业务强相关
            //业务逻辑(得到结果)
            int x = atoi(data1.c_str());
            int y = atoi(data2.c_str());
            const char* oper = op.c_str();
            std::string message;
            int z = 0;
            switch(*oper)
            {
                case '+':
                    z = x + y;
                    break;
                case '-':
                    z = x - y;
                    break;
                case '*':
                    z = x * y;
                    break;
                case '/':
                    if (y == 0)
                    {
                        message += "division by zero error ";
                    }
                    else
                    {
                        z = x / y;
                    }
                    break;
                case '%':
                    if (y == 0)
                    {
                        message += "remainder by zero error ";
                    }
                    else
                    {
                        z = x % y;
                    }
                    break;
                default:
                    break;
            }

            //构建响应,添加到p_ev->outbuffer
            if (y == 0)
            {
                message += data1;
                message += op;
                message += data2;
                message += separator;

                p_ev->_outbuffer += message;
            }
            else
            {
                message += data1;
                message += op;
                message += data2;
                message += "=";
                message += std::to_string(z);
                message += separator;

                p_ev->_outbuffer += message;
            }
        }
    }

    //尝试进行把数据进行发送
    //我们必须等待写条件就绪了,我们才能进行数据的发送
    //一般只需要将报文处理完之后,才需要进行发送
    //对于写事件来说,一般都是就绪的,只要发送缓冲区有位置,但是用户不一定就绪
    //所以对于写事件,我们一般都是按照自己的需要进行设置的,当用户准备好了,就可以进行设置
    if (!(p_ev->_outbuffer).empty())
    {
        //当你需要关注写事件的时候,一般默认是就绪的,及时发送缓冲区已经满了,但是epoll还是会进行通知的,但是send有可能发送不出去数据,而返回了
        //当发送缓冲区变多了,epoll会再一次进行通知的
        p_ev->_p_reactor->modify_read_write(p_ev->_sock, true, true);
    }

    return 0;
}

int sender(Event* p_ev)
{
    std::cout << "sender has been called" << std::endl;

    //对于发送来说,有三种情况
    //1.全部数据发送完成,返回值为1
    //2.数据没有发完,但是不能再继续发送了返回值为0
    //3.发送失败,返回值为-1
    int result = sender_core(p_ev->_sock, p_ev->_outbuffer);
    if (result == 1)
    {
        //按需设置
        p_ev->_p_reactor->modify_read_write(p_ev->_sock, true, false);
    }
    else if (result == 0)
    {
        //其实这里什么都没有做
        p_ev->_p_reactor->modify_read_write(p_ev->_sock, true, true);
    }
    else
    {
        //如果这个事件设置了errorer回调函数,那么就调用它
        if (p_ev->_errorer)
        {
            p_ev->_errorer(p_ev);
        }
        return -1;
    }
    return 0;
}

int errorer(Event* p_ev)
{
    std::cout << "errorer has been called" << std::endl;
    p_ev->_p_reactor->delete_event(p_ev);
    return 0;
}
